#include <scn.h>

#include <visual.h>
#include <line.h>
#include <utils.h>

/**
 * DESC: Load scene and display all the six faces
 *
 * IMP: HIGH
 */

static inline void
set_pixel_from_voxel( surface_t *surface,
		      const uint16_t x, const uint16_t y,
		      model3d_t *model,
		      const uint16_t i, const uint16_t j, const uint16_t k,
		      const uint16_t vmax )
{
  uint16_t d = VOXEL_AT( model, i, j, k );
  uint8_t v = 255 * ((float)d) / vmax;
  color_t c = { v, v, v };
  PIXEL_AT( surface, x, y ) = c;
}


int main( int argc, char *argv[] )
{
  char *filename;

  if ( argc >= 2 )
    filename = argv[ 1 ];
  else
    filename = "/tmp/RM-cabeca.scn";

  model3d_t *m = scn_load( filename );

  if ( m == NULL )
    {
      fprintf( stderr, "Could not load scene from %s\n", filename );
      return -1;
    }

  uint16_t vmax=0, i, j, k;
  for ( i=0; i < m->size.x; i++ )
    for ( j=0; j < m->size.y; j++ )
      for ( k=0; k < m->size.z; k++ )
	vmax = max( vmax, VOXEL_AT( m, i, j, k ) );

  uint16_t d = max( max( m->size.x, m->size.y ), m->size.z ) + 1;

  visual_init( d, d );

  line_t line;
  OBJECT_TRANSP( &line ) = 0.0;
  COLOR_FROM_ARGB( OBJECT_COLOR( &line ), COLOR_RED );

  surface_t *surface = surface_new( d, d );
  coord_t p0 = { 0, 0 };
  uint16_t x, y;

  /* Front */
  printf( "Front\n" );
  surface_clear( surface );
  for ( x=0; x < m->size.x; x++ )
    for ( y=0; y < m->size.y; y++ )
      set_pixel_from_voxel( surface, x, y,
			    m, x, y, 0,
			    vmax );
  SET_RECT( line.r, m->size.x, 0, m->size.x, m->size.y );
  line_draw( &line, surface );
  SET_RECT( line.r, 0, m->size.y, m->size.x, m->size.y );
  line_draw( &line, surface );

  visual_display( surface, p0 );
  visual_update();
  visual_waitkey();


  /* Back */
  printf( "Back\n" );
  surface_clear( surface );
  for ( x=0; x < m->size.x; x++ )
    for ( y=0; y < m->size.y; y++ )
      set_pixel_from_voxel( surface, x, y,
			    m, m->size.x - x - 1, y, m->size.z - 1,
			    vmax );
  SET_RECT( line.r, m->size.x, 0, m->size.x, m->size.y );
  line_draw( &line, surface );
  SET_RECT( line.r, 0, m->size.y, m->size.x, m->size.y );
  line_draw( &line, surface );

  visual_display( surface, p0 );
  visual_update();
  visual_waitkey();


  /* Top */
  printf( "Top\n" );
  surface_clear( surface );
  for ( x=0; x < m->size.x; x++ )
    for ( y=0; y < m->size.z; y++ )
      set_pixel_from_voxel( surface, x, y,
			    m, x, 0, m->size.z - y - 1,
			    vmax );
  SET_RECT( line.r, m->size.x, 0, m->size.x, m->size.z );
  line_draw( &line, surface );
  SET_RECT( line.r, 0, m->size.z, m->size.x, m->size.z );
  line_draw( &line, surface );

  visual_display( surface, p0 );
  visual_update();
  visual_waitkey();


  /* Bottom */
  printf( "Bottom\n" );
  surface_clear( surface );
  for ( x=0; x < m->size.x; x++ )
    for ( y=0; y < m->size.z; y++ )
      set_pixel_from_voxel( surface, x, y,
			    m, x, m->size.z - 1, y,
			    vmax );
  SET_RECT( line.r, m->size.x, 0, m->size.x, m->size.z );
  line_draw( &line, surface );
  SET_RECT( line.r, 0, m->size.z, m->size.x, m->size.z );
  line_draw( &line, surface );

  visual_display( surface, p0 );
  visual_update();
  visual_waitkey();


  /* Left */
  printf( "Left\n" );
  surface_clear( surface );
  for ( x=0; x < m->size.z; x++ )
    for ( y=0; y < m->size.y; y++ )
      set_pixel_from_voxel( surface, x, y,
			    m, 0, y, m->size.z - x - 1,
			    vmax );
  SET_RECT( line.r, m->size.z, 0, m->size.z, m->size.y );
  line_draw( &line, surface );
  SET_RECT( line.r, 0, m->size.y, m->size.z, m->size.y );
  line_draw( &line, surface );

  visual_display( surface, p0 );
  visual_update();
  visual_waitkey();


  /* Right */
  printf( "Right\n" );
  surface_clear( surface );
  for ( x=0; x < m->size.z; x++ )
    for ( y=0; y < m->size.y; y++ )
      set_pixel_from_voxel( surface, x, y,
			    m, m->size.x - 1, y, x,
			    vmax );
  SET_RECT( line.r, m->size.z, 0, m->size.z, m->size.y );
  line_draw( &line, surface );
  SET_RECT( line.r, 0, m->size.y, m->size.z, m->size.y );
  line_draw( &line, surface );

  visual_display( surface, p0 );
  visual_update();
  visual_waitkey();


  surface_free( surface );
  model3d_free( m );

  visual_quit();

  return 0;
}
